package common;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import math.probability.ProbDistribution;

public class StructuralModel {
	private int N;
	private ProbDistribution distX;
	private ProbDistribution distXi;
	private ProbDistribution distEps;
	private Double b0;
	private Double b1;
	private Map<Double, Double> data;
	
	private List<Double> smplX;
	private List<Double> smplXi;
	private List<Double> smplEps;
	private List<Double> smplU;
	private List<Double> smplV;
	
	
	
	
	public StructuralModel(int n, ProbDistribution distX,
			ProbDistribution distKsi, ProbDistribution distEps, Double b0,
			Double b1) {
		N = n;
		this.distX = distX;
		this.distXi = distKsi;
		this.distEps = distEps;
		this.b0 = b0;
		this.b1 = b1;
		
		generateNewData (); 
	}

	public StructuralModel(int n, ProbDistribution distX,
			ProbDistribution distKsi, ProbDistribution distEps, Double b0,
			Double b1, Random r) {
		N = n;
		this.distX = distX;
		this.distXi = distKsi;
		this.distEps = distEps;
		this.b0 = b0;
		this.b1 = b1;
		
		generateNewData (r); 
	}
	
	public void printData(String fileName) {
		try {
			PrintWriter out = new PrintWriter(new FileOutputStream(fileName));
			out.println("X,Xi,Eps,U,V");
			
			
			for (int i = 0; i < N; i++) {
				out.printf("%.4f,%.4f,%.4f,%.4f,%.4f\n",smplX.get(i),smplXi.get(i),
						smplEps.get(i),smplU.get(i),smplV.get(i) );
			}
			out.flush();
			out.close();
		} catch (FileNotFoundException e) {
		}
	}

	public Map<Double, Double> getNewData() {
		generateNewData ();
		return data;
	}
	
	public Map<Double, Double> getNewData(Random r) {
		generateNewData (r);
		return data;
	}
	
	public Map<Double, Double> getData() {
		return data;
	}
	
	private void generateNewData () {
		data = new HashMap<Double, Double>();
		smplX = distX.getSample(N);
		smplXi = distXi.getSample(N);
		smplEps = distEps.getSample(N);
		smplU = new ArrayList<Double>();
		smplV = new ArrayList<Double>();
		
		for (int i = 0; i < N; i++) {
			Double V = (b0+b1*smplX.get(i) + smplEps.get(i));
			Double U = (smplX.get(i) + smplXi.get(i));
			smplU.add(U);
			smplV.add(V);
			
			data.put(U, V);
		}
	}
	
	private void generateNewData (Random r) {
		data = new HashMap<Double, Double>();
		smplX = distX.getSample(N);
		smplXi = distXi.getSample(N);
		smplEps = distEps.getSample(N);
		smplU = new ArrayList<Double>();
		smplV = new ArrayList<Double>();
		for (int i = 0; i < N; i++) {
			Double V = (b0+b1*smplX.get(i) + smplEps.get(i));
			Double U = (smplX.get(i) + smplXi.get(i));
			smplU.add(U);
			smplV.add(V);
			data.put(U, V);
		}
	}
	
	public List<Double> getU() {
		return new ArrayList<Double>(data.keySet()); 
	}
	
	public List<Double> getV() {
		return new ArrayList<Double>(data.values()); 
	}


	public List<Double> getSmplX() {
		return smplX;
	}


	public List<Double> getSmplXi() {
		return smplXi;
	}


	public List<Double> getSmplEps() {
		return smplEps;
	}

	public List<Double> getSmplU() {
		return smplU;
	}

	public List<Double> getSmplV() {
		return smplV;
	}
	
	
	

}
